package org.polyforms.repository.strategy.support;

import java.lang.reflect.Method;
import java.util.Set;

import javax.inject.Inject;
import javax.inject.Named;

import org.polyforms.repository.executor.Executor;
import org.polyforms.repository.executor.NameBasedExecutor;
import org.polyforms.repository.strategy.ExecutorFindingStrategy;

/**
 * Strategy of finding {@link Executor} inheriting {@link NameBasedExecutor} for specific method.
 * 
 * @author Kuisong Tong
 * @since 1.0
 */
@Named
public final class NameBasedExecutorFindingStrategy implements ExecutorFindingStrategy {
    private static final String EMPTY_STRING = "";

    private final Set<NameBasedExecutor> executors;

    /**
     * Create an instance with {@link NameBasedExecutor}s.
     */
    @Inject
    public NameBasedExecutorFindingStrategy(final Set<NameBasedExecutor> executors) {
        this.executors = executors;
    }

    /**
     * {@inheritDoc}
     */
    public Executor getExecutor(final Method method) {
        for (final NameBasedExecutor executor : executors) {
            if (matches(executor, method)) {
                return executor;
            }
        }
        return Executor.UNSUPPORT;
    }

    private boolean matches(final NameBasedExecutor executor, final Method method) {
        final String methodName = method.getName();
        final String prefix = getPrefix(executor, methodName);
        return !EMPTY_STRING.equals(prefix) && methodName.length() > prefix.length();
    }

    private String getPrefix(final NameBasedExecutor executor, final String methodName) {
        for (final String prefix : executor.getPrefixes()) {
            if (methodName.startsWith(prefix)) {
                return prefix;
            }
        }

        return EMPTY_STRING;
    }
}
